package timing.ukulele.flow.service;

import timing.ukulele.flow.exception.NoUserException;
import timing.ukulele.flow.extention.UserTaskExtensionElementProperty;
import timing.ukulele.flow.request.SetTaskAssigneeReq;
import timing.ukulele.flow.vo.ExecuteVO;
import timing.ukulele.flow.vo.MultiTaskVO;
import timing.ukulele.flow.vo.TaskVO;
import timing.ukulele.flow.vo.UserVO;
import lombok.extern.slf4j.Slf4j;
import org.activiti.bpmn.model.BpmnModel;
import org.activiti.bpmn.model.ExtensionAttribute;
import org.activiti.bpmn.model.ExtensionElement;
import org.activiti.bpmn.model.FlowElement;
import org.activiti.bpmn.model.UserTask;
import org.activiti.engine.HistoryService;
import org.activiti.engine.ProcessEngine;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.history.HistoricIdentityLink;
import org.activiti.engine.history.HistoricTaskInstance;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.IdentityLink;
import org.activiti.engine.task.Task;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.ExceptionTranslationStrategy;
import org.springframework.data.redis.FallbackExceptionTranslationStrategy;
import org.springframework.data.redis.RedisConnectionFailureException;
import org.springframework.data.redis.connection.jedis.JedisConverters;
import org.springframework.data.redis.core.RedisConnectionUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@Service
@Slf4j
public class OperateTaskService implements UserTaskExtensionElementProperty {

//    @Resource
//    private Cache cache;

    public final RuntimeService runtimeService;
    public final ProcessEngine processEngine;
    public final TaskService taskService;
    public final FlowUserInfoService flowUserInfoService;
    public final HistoryService historyService;

    public OperateTaskService(RuntimeService runtimeService, ProcessEngine processEngine, TaskService taskService,
                              FlowUserInfoService flowUserInfoService, HistoryService historyService) {
        this.runtimeService = runtimeService;
        this.processEngine = processEngine;
        this.taskService = taskService;
        this.flowUserInfoService = flowUserInfoService;
        this.historyService = historyService;
    }


    @Transactional(rollbackFor = Exception.class)
    public String startFirstComplete(ExecuteVO executeVO) throws Exception {
        ProcessInstance instance;
        Map<String, Object> params;
        if (!CollectionUtils.isEmpty(executeVO.getParams())) {
            params = executeVO.getParams();
        } else {
            params = new HashMap<>(2);
        }
        params.put("startUser", executeVO.getStartUser());
        if (!CollectionUtils.isEmpty(executeVO.getInstances())) {
            params.put("instances",
                    executeVO.getInstances().stream().map(MultiTaskVO::getTaskName).collect(Collectors.toList()));
        }
        instance = runtimeService.startProcessInstanceByKeyAndTenantId(executeVO.getProcessKey(), params,
                executeVO.getTenantId());
        if (instance != null) {
            //获取第一步任务并执行 =
            Task task = processEngine.getTaskService().createTaskQuery().processInstanceId(instance.getId()).active().singleResult();
            taskService.complete(task.getId());
            //获取下一步活动的任务
            List<Task> nextTasks =
                    taskService.createTaskQuery().processInstanceId(executeVO.getProcessInstanceId()).active().list();
            publicFindTasks(nextTasks, executeVO);
        }
        return instance.getId();
    }

    /**
     * 开始任务
     *
     * @param executeVO
     */
    @Transactional(rollbackFor = Exception.class)
    public Map<String, Object> start(ExecuteVO executeVO) throws Exception {
        ProcessInstance instance;
        Map<String, Object> params;
        if (!CollectionUtils.isEmpty(executeVO.getParams())) {
            params = executeVO.getParams();
        } else {
            params = new HashMap<>(2);
        }
        params.put("startUser", executeVO.getStartUser());
        if (!CollectionUtils.isEmpty(executeVO.getInstances())) {
            params.put("instances",
                    executeVO.getInstances().stream().map(MultiTaskVO::getTaskName).collect(Collectors.toList()));
        }
        instance = runtimeService.startProcessInstanceByKeyAndTenantId(executeVO.getProcessKey(), params,
                executeVO.getTenantId());
        if (instance != null) {
            Map<String, Object> result = new HashMap<>(4);
            // 流程实例ID
            result.put("procInstId", instance.getId());
            // 流程定义ID
            result.put("processDefinitionKey", instance.getProcessDefinitionId());
            // taskVO集合
            List<TaskVO> taskVOS;
            //获取下一步任务
            List<Task> tasks =
                    processEngine.getTaskService().createTaskQuery().processInstanceId(instance.getId()).active().list();
            //先判断tasks中各个task参数中assigneeType字段值
            taskVOS = findTasksByAssigneeType(tasks, executeVO);
            if (taskVOS.size() > 0) {
                result.put("tasks", taskVOS);
            }
            return result;
        } else {
            throw new Exception("找不到该流程实例!");
        }
    }

    /**
     * 执行任务
     *
     * @param executeVO
     */
    @Transactional(rollbackFor = Exception.class)
    public List<TaskVO> completeTask(ExecuteVO executeVO) throws Exception {
        // taskVO集合
        List<TaskVO> taskVOS;
        //获取任务
        Task task = taskService.createTaskQuery()
                .processInstanceId(executeVO.getProcessInstanceId())
                .taskId(executeVO.getTaskId())
                .singleResult();
        //        String startUser = String.valueOf(taskService.getVariable(taskId, "startUser"));
        //校验前端传过来的assignee是否为该task列表中的待执行人
        //        List<UserVO> userVOList = findTaskUsers(task, startUser, assignee);
        //        if (CollectionUtils.isEmpty(userVOList)) {
        //            throw new Exception("非该用户执行的任务！");
        //        } else {
        //            boolean isThisAssignee = userVOList.stream().anyMatch(ele -> assignee.equals(ele.getUsername()));
        //            if (!isThisAssignee) {
        //                throw new Exception("非该用户执行的任务！");
        //            }
        //        }
        String startUser = String.valueOf(taskService.getVariable(executeVO.getTaskId(), "startUser"));
        Map<String, Object> params;
        if (!CollectionUtils.isEmpty(executeVO.getParams())) {
            params = executeVO.getParams();
        } else {
            params = new HashMap<>();
        }
        if (!CollectionUtils.isEmpty(executeVO.getInstances())) {
            params.put("instances", executeVO.getInstances());
        }
        params.put("startUser", startUser);
        executeVO.setStartUser(startUser);
        if (StringUtils.isEmpty(task.getAssignee())) {
            taskService.setAssignee(task.getId(), executeVO.getAssignee());
        }
        for (String key : params.keySet()) {
            if (key.startsWith("g_")) {
                taskService.setVariable(task.getId(), key, params.get(key));
            } else {
                taskService.setVariableLocal(task.getId(), key, params.get(key));
            }
        }
        taskService.complete(task.getId());
        //获取下一步活动的任务
        List<Task> nextTasks =
                taskService.createTaskQuery().processInstanceId(executeVO.getProcessInstanceId()).active().list();
        taskVOS = findTasksByAssigneeType(nextTasks, executeVO);
        return taskVOS;
    }

    /**
     * 执行任务
     *
     * @param setTaskAssigneeReqs
     */
    @Transactional(rollbackFor = Exception.class)
    public void setTaskAssignee(List<SetTaskAssigneeReq> setTaskAssigneeReqs) {
        try {
            for (SetTaskAssigneeReq setTaskAssigneeReq : setTaskAssigneeReqs) {
                String taskId = setTaskAssigneeReq.getTaskId();
                String users = setTaskAssigneeReq.getUsers();
                String departs = setTaskAssigneeReq.getDeparts();
                String roles = setTaskAssigneeReq.getRoles();
                String currentUser = setTaskAssigneeReq.getCurrentUser();
                Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
                if (StringUtils.isEmpty(users)) {
                    if (StringUtils.isEmpty(departs) && StringUtils.isEmpty(roles)) {
                        return;
                    } else {
                        List<UserVO> userVOs =
                                flowUserInfoService.getUserList(null, null, departs, null, roles, null, null, null,
                                        currentUser, null);
                        if (!CollectionUtils.isEmpty(userVOs)) {
                            if (userVOs.size() > 1) {
                                List<String> candidateUsers =
                                        userVOs.stream().map(UserVO::getUsername).collect(Collectors.toList());
                                candidateUsers.stream().forEach(e -> taskService.addCandidateUser(task.getId(), e));
                            } else {
                                task.setAssignee(userVOs.get(0).getUsername());
                                processEngine.getTaskService().saveTask(task);
                            }
                        }
                    }
                } else {
                    String[] userIds = users.split(",");
                    List<String> userIdList = Arrays.asList(userIds);
                    if (userIdList.size() > 1) {
                        userIdList.stream().forEach(e -> taskService.addCandidateUser(task.getId(), e));
                    } else {
                        task.setAssignee(userIdList.get(0));
                        processEngine.getTaskService().saveTask(task);
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 查询该任务下根据参数查出的候选人
     *
     * @param task
     * @param startUser 流程启动用户
     * @param flowUser  当前用户
     */
    private List<UserVO> findTaskUsers(Task task, String startUser, String flowUser) {
        Map<String, String> property = this.findRunningTaskParams(task);
        if (CollectionUtils.isEmpty(property)) {
            return null;
        }
        String areaParam = property.get(area);
        String departmentParam = property.get(department);
        String roleParam = property.get(role);
        String ruleParam = property.get(rule);
        String useTypeParam = property.get(userType);
        String roleIsAndParam = "false".equals(property.get(roleIsAnd)) ? "0" : "1";
        log.info("请求接口参数：userpara=null,uuid=null,departmentParam=" + departmentParam + ",areaParam=" + areaParam + ",roleParam="
                + roleParam + ",roleIsAndParam=" + ",useTypeParam=" + useTypeParam + ",startUser=" + startUser + ",flowUser=" + flowUser + ",ruleParam=" + ruleParam);
        //todo 测试
        List<UserVO> users =
                flowUserInfoService.getUserList(null, null, departmentParam, areaParam, roleParam, roleIsAndParam,
                        useTypeParam, startUser, flowUser, ruleParam);
        return users;
    }

    /**
     * 获取用户正在运行任务的自定义参数
     *
     * @param task
     * @return
     */
    public Map<String, String> findRunningTaskParams(Task task) {
        BpmnModel bpmnModel = processEngine.getRepositoryService().getBpmnModel(task.getProcessDefinitionId());
        // 获得流程定义
        FlowElement flowElement = bpmnModel.getMainProcess().getFlowElement(task.getTaskDefinitionKey());
        if (flowElement == null) {
            return null;
        }
        if (!(flowElement instanceof UserTask)) {
            return null;
        }
        UserTask userTask = (UserTask) flowElement;
        //
        Map<String, String> property = new HashMap<>();
        //解析
        Map<String, List<ExtensionElement>> customerProperties = userTask.getExtensionElements();
        if (!CollectionUtils.isEmpty(customerProperties) && customerProperties.containsKey(elememt)) {
            ExtensionElement e = customerProperties.get(elememt).get(0);
            Map<String, List<ExtensionAttribute>> attributes = e.getAttributes();
            attributes.forEach((key, attr) ->
            {
                for (ExtensionAttribute extensionAttribute : attr) {
                    property.put(extensionAttribute.getName(), extensionAttribute.getValue());
                }
            });
        }
        return property;
    }

    /**
     * 获取用户历史任务的自定义参数
     *
     * @param historicTaskInstance
     * @return
     */
    public Map<String, String> findHistoryTaskParams(HistoricTaskInstance historicTaskInstance) {
        BpmnModel bpmnModel = processEngine.getRepositoryService().getBpmnModel(historicTaskInstance.getProcessDefinitionId());
        // 获得流程定义
        FlowElement flowElement = bpmnModel.getMainProcess().getFlowElement(historicTaskInstance.getTaskDefinitionKey());
        if (flowElement == null) {
            return null;
        }
        if (!(flowElement instanceof UserTask)) {
            return null;
        }
        UserTask userTask = (UserTask) flowElement;
        //
        Map<String, String> property = new HashMap<>();
        //解析
        Map<String, List<ExtensionElement>> customerProperties = userTask.getExtensionElements();
        if (!CollectionUtils.isEmpty(customerProperties) && customerProperties.containsKey(elememt)) {
            ExtensionElement e = customerProperties.get(elememt).get(0);
            Map<String, List<ExtensionAttribute>> attributes = e.getAttributes();
            attributes.forEach((key, attr) ->
            {
                for (ExtensionAttribute extensionAttribute : attr) {
                    property.put(extensionAttribute.getName(), extensionAttribute.getValue());
                }
            });
        }
        return property;
    }

    /**
     * 判断任务assigneeType类型，设置执行人
     *
     * @param tasks
     * @param executeVO
     * @return
     */
    public List<TaskVO> findTasksByAssigneeType(List<Task> tasks, ExecuteVO executeVO) throws Exception {
        String assignee = executeVO.getAssignee();
        String nextAssignee = executeVO.getNextAssignee();
        String uuid = executeVO.getUuid();
        String departs = executeVO.getDeparts();
        String areaCode = executeVO.getAreacode();
        String roles = executeVO.getRoles();
        String island = executeVO.getIsand();
        String usertype = executeVO.getUsertype();
        String ruleCode = executeVO.getRulecode();
        String userPara = executeVO.getUserpara();
        String startUser = executeVO.getStartUser();

        //判断该任务是否为多实例任务
        List<MultiTaskVO> instances = executeVO.getInstances();
        //任务有效时间
        Date dueDate = executeVO.getDueDate();
        List<TaskVO> taskVOS = new ArrayList<>();
        if (!CollectionUtils.isEmpty(tasks)) {
            if (!CollectionUtils.isEmpty(instances)) {
                //说明这些任务是多实例产生的
                for (int i = 0; i < instances.size(); i++) {
                    TaskVO vo = new TaskVO();
                    if (StringUtils.isEmpty(instances.get(i).getNextAssignee())) {
                        String uuid1 = instances.get(i).getUuid();
                        String departs1 = instances.get(i).getDeparts();
                        String areaCode1 = instances.get(i).getAreacode();
                        String roles1 = instances.get(i).getRoles();
                        String island1 = instances.get(i).getIsand();
                        String usertype1 = instances.get(i).getUsertype();
                        String ruleCode1 = instances.get(i).getRulecode();
                        String userPara1 = instances.get(i).getUserpara();
                        List<UserVO> users =
                                flowUserInfoService.getUserList(userPara1, uuid1, departs1, areaCode1, roles1, island1,
                                        usertype1, startUser, executeVO.getAssignee(), ruleCode1);
                        if (!CollectionUtils.isEmpty(users)) {
                            List<String> configureUserList =
                                    users.stream().map(UserVO::getUsername).collect(Collectors.toList());
                            StringBuffer configureUsers = new StringBuffer();
                            //并将人员信息返回
                            for (int j = 0; j < configureUserList.size(); j++) {
                                if (j == configureUserList.size() - 1) {
                                    configureUsers.append(configureUserList.get(j));
                                } else {
                                    configureUsers.append(configureUserList.get(j) + ",");
                                }
                            }
                            vo.setConfigureUsers(configureUsers.toString());
                            if (users.size() > 1) {
                                List<String> candidateUsers =
                                        users.stream().map(UserVO::getUsername).collect(Collectors.toList());
                                for (String candidateUser : candidateUsers) {
                                    taskService.addCandidateUser(tasks.get(i).getId(), candidateUser);
                                }
                            } else {
                                taskService.setAssignee(tasks.get(i).getId(), users.get(0).getUsername());
                            }
                        } else {
                            String error = "流程图配置参数未查到相关人员!";
                            log.error(error);
                            throw new NoUserException(error);
                        }
                    } else {
                        String[] userIds = instances.get(i).getNextAssignee().split(",");
                        List<String> userIdList = Arrays.asList(userIds);
                        if (userIdList.size() > 1) {
                            for (String userId : userIdList) {
                                taskService.addCandidateUser(tasks.get(i).getId(), userId);
                            }
                        } else {
                            taskService.setAssignee(tasks.get(i).getId(), userIdList.get(0));
                        }
                    }
                    BeanUtils.copyProperties(tasks.get(i), vo);
                    taskVOS.add(vo);
                }
            } else {
                for (Task task : tasks) {
                    TaskVO vo = new TaskVO();
                    Map<String, String> property = this.findRunningTaskParams(task);
                    //任务设置有效时间
                    if (!StringUtils.isEmpty(dueDate)) {
                        taskService.setDueDate(task.getId(), dueDate);
                    } else {
                        String executeTimeLimitString = property.get(executeTimeLimit);
                        if (!(StringUtils.isEmpty(executeTimeLimitString) || "0".equals(executeTimeLimitString))) {
                            Date date = task.getCreateTime();
                            date.setTime(date.getTime() + Long.parseLong(executeTimeLimitString) * 60 * 1000);
                            taskService.setDueDate(task.getId(), date);
                        }
                    }
                    List<IdentityLink> identityLinks = taskService.getIdentityLinksForTask(task.getId());
                    if (StringUtils.isEmpty(task.getAssignee()) && CollectionUtils.isEmpty(identityLinks)) {
                        String type = property.get(assigneeType);
                        if (StringUtils.hasLength(type) && type.equals("1")) {
                            //前端指定
                            if (StringUtils.isEmpty(nextAssignee)) {
                                Map<String, String> propertyMap = this.findRunningTaskParams(task);
                                String areaParam = propertyMap.get(area);
                                if (!StringUtils.isEmpty(areaCode)) {
                                    areaParam = areaCode;
                                }
                                String departmentParam = propertyMap.get(department);
                                if (!StringUtils.isEmpty(departs)) {
                                    departmentParam = departs;
                                }
                                String roleParam = propertyMap.get(role);
                                if (!StringUtils.isEmpty(roles)) {
                                    roleParam = roles;
                                }
                                String ruleParam = propertyMap.get(rule);
                                if (!StringUtils.isEmpty(ruleCode)) {
                                    ruleParam = ruleCode;
                                }
                                String useTypeParam = propertyMap.get(userType);
                                if (!StringUtils.isEmpty(usertype)) {
                                    useTypeParam = usertype;
                                }
                                String roleIsAndParam = "false".equals(propertyMap.get(roleIsAnd)) ? "0" : "1";
                                if (!StringUtils.isEmpty(island)) {
                                    roleIsAndParam = island;
                                }
                                if (StringUtils.isEmpty(departmentParam) && StringUtils.isEmpty(areaParam) && StringUtils.isEmpty(
                                        roleParam) && StringUtils.isEmpty(roleIsAndParam) && StringUtils.isEmpty(useTypeParam)
                                        && StringUtils.isEmpty(ruleParam)) {
                                    throw new Exception("前端或前端对应的后端配置需指定下步任务的执行人或相关参数!");
                                } else {
                                    List<UserVO> userVOs =
                                            flowUserInfoService.getUserList(userPara, uuid, departmentParam, areaParam, roleParam, roleIsAndParam,
                                                    useTypeParam, startUser, startUser, ruleParam);
                                    if (userVOs == null) {
                                        String error = "前端指定的参数未查询到人员!" + "departmentParam =" + departmentParam + ";areaParam =" + areaParam
                                                + ";roleParam =" + roleParam + ";roleIsAndParam =" + roleIsAndParam + ";useTypeParam =" + useTypeParam + ";ruleParam =" + ruleParam;
                                        log.error(error);
                                        throw new NoUserException(error);
                                    }
                                    if (!CollectionUtils.isEmpty(userVOs)) {
                                        if (userVOs.size() > 1) {
                                            List<String> candidateUsers =
                                                    userVOs.stream().map(UserVO::getUsername).collect(Collectors.toList());
                                            candidateUsers.forEach(e -> taskService.addCandidateUser(task.getId(), e));
                                        } else {
                                            taskService.setAssignee(task.getId(), userVOs.get(0).getUsername());
                                        }
                                    } else {
                                        String error = "前端指定的参数未查询到人员!" + "departmentParam =" + departmentParam + ";areaParam =" + areaParam
                                                + ";roleParam =" + roleParam + ";roleIsAndParam =" + roleIsAndParam + ";useTypeParam =" + useTypeParam + ";ruleParam =" + ruleParam;
                                        log.error(error);
                                        throw new NoUserException(error);
                                    }
                                }
                            } else {
                                String[] userIds = nextAssignee.split(",");
                                List<String> userIdList = Arrays.asList(userIds);
                                if (userIdList.size() > 1) {
                                    userIdList.forEach(e -> taskService.addCandidateUser(task.getId(), e));
                                } else {
                                    taskService.setAssignee(task.getId(), userIdList.get(0));
                                }
                            }
                            vo.setAssigneeType("1");
                            //人员由前端指定，将此类型task集合返回
                            BeanUtils.copyProperties(task, vo);
                            vo.setProperties(property);
                        } else if (StringUtils.hasLength(type) && type.equals("0")) {
                            //由流程图配置
                            vo.setAssigneeType("0");
                            List<UserVO> users = findTaskUsers(task, executeVO.getStartUser(), executeVO.getStartUser());
                            if (!CollectionUtils.isEmpty(users)) {
                                List<String> configureUserList =
                                        users.stream().map(UserVO::getUsername).collect(Collectors.toList());
                                StringBuffer configureUsers = new StringBuffer();
                                //并将人员信息返回
                                for (int i = 0; i < configureUserList.size(); i++) {
                                    if (i == configureUserList.size() - 1) {
                                        configureUsers.append(configureUserList.get(i));
                                    } else {
                                        configureUsers.append(configureUserList.get(i) + ",");
                                    }
                                }
                                vo.setConfigureUsers(configureUsers.toString());
                                if (users.size() > 1) {
                                    List<String> candidateUsers =
                                            users.stream().map(UserVO::getUsername).collect(Collectors.toList());
                                    candidateUsers.forEach(e -> taskService.addCandidateUser(task.getId(), e));
                                } else {
                                    taskService.setAssignee(task.getId(), users.get(0).getUsername());
                                }
                                BeanUtils.copyProperties(task, vo);
                                vo.setProperties(property);
                            } else {
                                String error = "流程图配置参数未查到相关人员!";
                                log.error(error);
                                throw new NoUserException(error);
                            }
                        } else {
                            //同前某节点一样
                            vo.setAssigneeType("2");
                            String relationNodeId = property.get(UserTaskExtensionElementProperty.relationNodeId);
                            //list其实有2个对象，研究了半天第二条不知道怎么冒出来的，数据库表根本没有这条数据
                            HistoricTaskInstance historicTaskInstance = historyService.createHistoricTaskInstanceQuery()
                                    .processInstanceId(task.getProcessInstanceId())
                                    .taskDefinitionKey(relationNodeId)
                                    .list().get(0);
                            List<HistoricIdentityLink> historicIdentityLinksForTask =
                                    historyService.getHistoricIdentityLinksForTask(historicTaskInstance.getId());
                            if (!CollectionUtils.isEmpty(historicIdentityLinksForTask)) {
                                for (HistoricIdentityLink historicIdentityLink : historicIdentityLinksForTask) {
                                    taskService.addCandidateUser(task.getId(), historicIdentityLink.getUserId());
                                }
                            } else {
                                taskService.setAssignee(task.getId(), historicTaskInstance.getAssignee());
                            }
                            BeanUtils.copyProperties(task, vo);
                            vo.setProperties(property);
                        }
                    }
                    //任务锁状态
                    vo.setLocked(checkTaskLock(task.getId()));
                    taskVOS.add(vo);
                }
            }
        }
        return taskVOS;
    }

    /**
     * 所有系统公共的最基础的任务设置执行人方法
     *
     * @param tasks
     * @param executeVO
     * @return
     */
    public List<TaskVO> publicFindTasks(List<Task> tasks, ExecuteVO executeVO) {
        String nextAssignee = executeVO.getNextAssignee();
        //判断该任务是否为多实例任务
        List<MultiTaskVO> instances = executeVO.getInstances();
        List<TaskVO> taskVOS = new ArrayList<>();
        if (!CollectionUtils.isEmpty(tasks)) {
            if (!CollectionUtils.isEmpty(instances)) {
                //说明这些任务是多实例产生的
                for (int i = 0; i < instances.size(); i++) {
                    TaskVO vo = new TaskVO();
                    String[] userIds = instances.get(i).getNextAssignee().split(",");
                    List<String> userIdList = Arrays.asList(userIds);
                    if (userIdList.size() > 1) {
                        for (String userId : userIdList) {
                            taskService.addCandidateUser(tasks.get(i).getId(), userId);
                        }
                    } else {
                        taskService.setAssignee(tasks.get(i).getId(), userIdList.get(0));
                    }
                    BeanUtils.copyProperties(tasks.get(i), vo);
                    taskVOS.add(vo);
                }
            } else {
                for (Task task : tasks) {
                    TaskVO vo = new TaskVO();
                    Map<String, String> property = this.findRunningTaskParams(task);
                    List<IdentityLink> identityLinks = taskService.getIdentityLinksForTask(task.getId());
                    if (StringUtils.isEmpty(task.getAssignee()) && CollectionUtils.isEmpty(identityLinks)) {
                        //前端指定
                        String[] userIds = nextAssignee.split(",");
                        List<String> userIdList = Arrays.asList(userIds);
                        if (userIdList.size() > 1) {
                            userIdList.forEach(e -> taskService.addCandidateUser(task.getId(), e));
                        } else {
                            taskService.setAssignee(task.getId(), userIdList.get(0));
                        }
                        //人员由前端指定，将此类型task集合返回
                        BeanUtils.copyProperties(task, vo);
                        vo.setProperties(property);
                    }
                    taskVOS.add(vo);
                }
            }
        }
        return taskVOS;
    }

    /**
     * 所有系统公共的最基础的执行任务方法
     *
     * @param executeVO
     */
    @Transactional(rollbackFor = Exception.class)
    public void publicCompleteTask(ExecuteVO executeVO) throws Exception {
        //获取任务
        Task task = taskService.createTaskQuery()
                .processInstanceId(executeVO.getProcessInstanceId())
                .taskId(executeVO.getTaskId())
                .singleResult();
        String startUser = String.valueOf(taskService.getVariable(executeVO.getTaskId(), "startUser"));
        Map<String, Object> params;
        if (!CollectionUtils.isEmpty(executeVO.getParams())) {
            params = executeVO.getParams();
        } else {
            params = new HashMap<>();
        }
        if (!CollectionUtils.isEmpty(executeVO.getInstances())) {
            params.put("instances", executeVO.getInstances());
        }
        params.put("startUser", startUser);
        executeVO.setStartUser(startUser);
        for (String key : params.keySet()) {
            if (key.startsWith("g_")) {
                taskService.setVariable(task.getId(), key, params.get(key));
            } else {
                taskService.setVariableLocal(task.getId(), key, params.get(key));
            }
        }
        taskService.complete(task.getId());

        //获取下一步活动的任务
        List<Task> nextTasks =
                taskService.createTaskQuery().processInstanceId(executeVO.getProcessInstanceId()).active().list();
        //设置下步执行人
        publicFindTasks(nextTasks, executeVO);
    }

    public List<UserVO> testGetUser(String userpara, String uuid, String depcode, String areacode, String roles, String isand,
                              String usertype, String startuser, String flowuser, String rulecode) {
        List<UserVO> userList = flowUserInfoService.getUserList(userpara, uuid, depcode, areacode, roles, isand, usertype, startuser, flowuser, rulecode);
        return userList;
    }

    @Autowired
    private RedisTemplate redisTemplate;
    private static final ExceptionTranslationStrategy EXCEPTION_TRANSLATION =
            new FallbackExceptionTranslationStrategy(JedisConverters.exceptionConverter());

    private Object getRedis(String key) {
        try {
            this.redisTemplate.setEnableTransactionSupport(false);
            Object cacheObject = this.redisTemplate.opsForValue().get(key);
            return cacheObject;
        } catch (Exception ee) {
            if (ee instanceof NullPointerException) {
                throw ee;
            } else {
                DataAccessException exception = EXCEPTION_TRANSLATION.translate(ee);
                if (exception instanceof RedisConnectionFailureException) {
                    RedisConnectionUtils.unbindConnection(this.redisTemplate.getConnectionFactory());
                    Object cacheObject = this.redisTemplate.opsForValue().get(key);
                    return cacheObject;
                } else {
                    throw ee;
                }
            }
        }
    }

    /**
     * 检查任务锁状态
     *
     * @param taskId
     */
    public Boolean checkTaskLock(String taskId) {
        //先校验该任务是否为预处理的任务
        // Object cacheObject = cache.get("task_lock_" + taskId);
        Object cacheObject = getRedis("timing_flow_task_lock_" + taskId);
        return cacheObject == null;
    }
}
